/**
 *<div id="app">hello vue</div>
 *{tag:'div'
   
  }
 * @export
 * @param {*} el
 */
// 用于解析标签和属性的正则表达式
const attribute =
  /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/; // 找id class
// const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`; //标签名称
const qnameCapture = `((?:${ncname}\\:)?${ncname})`; //<span:xx>
const startTagOpen = new RegExp(`^<${qnameCapture}`); // 标签开头的正则 捕获的内容是标签名
const startTagClose = /^\s*(\/?)>/; //匹配标签结束的
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`); //匹配标签结尾的 </div>
export const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
// const doctype = /^<!DOCTYPE [^>]+>/i
export function parseHTML(html) {
  //创建ast语法树
  function createASTElement(tag, attrs) {
    return {
      tag, //div
      attrs,
      children: [], //子节点
      type: 1, //类型
      parent: null,
    };
  }
  let root; //根元素
  let cerateParent; //当前元素的父亲
  // 数据结构 栈
  let stack = []; //[div,h] div h 入栈 遇到</h> h出栈 变成[div] 即div为h的父亲
  //开始标签
  function start(tag, attrs) {
    let element = createASTElement(tag, attrs);
    if (!root) {
      root = element;
    }
    cerateParent = element;
    stack.push(element);
  }
  //文本内容
  function charts(text) {
    //空格
    text = text.replace(/\s*/g, "");
    text = text.replace(/&lt;/g, "<");
    text = text.replace(/&gt;/g, ">");
    if (text) {
      cerateParent.children.push({
        type: 3,
        text,
      });
    }
  }
  //结束标签
  function end() {
    //删除 并获取最后一个元素
    let element = stack.pop();
    cerateParent = stack[stack.length - 1];
    if (cerateParent) {
      element.parent = cerateParent.tag;
      cerateParent.children.push(element);
    }
  }

  while (html) {
    //为空时结束
    //判断标签  < >
    let textEnd = html.indexOf("<"); //0
    if (textEnd === 0) {
      //1.开始标签
      const startTagMatch = parseStartTag();
      if (startTagMatch) {
        start(startTagMatch.tagName, startTagMatch.attrs);
        continue;
      }
      //2.结束标签
      let endTagMatch = html.match(endTag);
      if (endTagMatch) {
        advance(endTagMatch[0].length);
        end(endTagMatch[1]);
        continue;
      }
      continue;
    }
    //开始解析文本
    let text;
    if (textEnd > 0) {
      //获取文本内容
      text = html.substring(0, textEnd);
    }
    if (text) {
      advance(text.length);
      charts(text);
    }
  }
  function parseStartTag() {
    const start = html.match(startTagOpen); //1 结果 2 false
    if (start) {
      //创建ast语法树
      //<div id="app">hello vue</div>
      let match = {
        tagName: start[1],
        attrs: [],
      };
      //删除查找过的标签
      advance(start[0].length);
      let attr, end;
      while (
        !(end = html.match(startTagClose)) &&
        (attr = html.match(attribute))
      ) {
        match.attrs.push({
          name: attr[1],
          value: attr[3] || attr[4] || attr[5],
        });
        advance(attr[0].length);
      }
      if (end) {
        // >hello vue {{msg}}</div> 去除第一个>
        advance(end[0].length);
        return match;
      }
    }
  }
  function advance(n) {
    html = html.substring(n);
  }
  return root;
}
